package org.batatasframework.support.controllers;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.batatasframework.support.database.IdentifyTableGenerator;
import org.batatasframework.support.database.metadatas.TableMetadata;
import org.batatasframework.support.definition.TableDefinition;
import org.batatasframework.support.definition.TableDefinitionBuilder;
import org.batatasframework.support.event.SearchableHttpRequest;
import org.batatasframework.support.event.internal.DefaultSearchableHttpRequest;
import org.batatasframework.support.factory.TableDefinitionFactory;
import org.batatasframework.support.searchable.SearchableHandler;
import org.batatasframework.support.searchable.SearchableInputStream;
import org.batatasframework.support.searchable.SearchablePlatform;
import org.batatasframework.support.searchable.writer.ExcelResultWriter;
import org.batatasframework.support.searchable.writer.ObjectResultWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.bonoon.core.plugins.AccountService;
import cn.bonoon.entities.AccountEntity;
import cn.bonoon.kernel.events.PanelEvent;
import cn.bonoon.kernel.security.LogonUser;
import cn.bonoon.kernel.support.IOperator;
import cn.bonoon.kernel.web.controllers.AbstractPanelController;
import cn.bonoon.kernel.web.models.JsonResult;
import cn.bonoon.kernel.web.models.PanelModel;
import cn.bonoon.util.SleepUtil;

public abstract class AbstractSearchController extends AbstractPanelController{
	
	private TableDefinition tableDefinition;

	@Autowired
	@Qualifier("tableDefinitionFactory")
	protected TableDefinitionFactory tableDefinitionFactory;
	@Autowired
	AccountService accountService;
	protected TableDefinition loadTableDefinition() throws Exception{
		if(null == tableDefinition){
			TableMetadata sourceTableMetadata = tableDefinitionFactory.getDatabaseMetadataSources().getTableMetadata(getDefinitionName());
			if(null == sourceTableMetadata){
				try(TableDefinitionBuilder tdBuilder = tableDefinitionFactory.buildSearchableContextBuilder(null, getCatalog(), getDefinitionName())){
					initDefinition(tdBuilder);
					
					tableDefinition = tdBuilder.build();
				}
			}else{
				try(TableDefinitionBuilder tdBuilder = tableDefinitionFactory.buildSearchableContextBuilder(sourceTableMetadata)){
					initDefinition(tdBuilder);
					
					tableDefinition = tdBuilder.build();
				}
			}
		}
		return tableDefinition;
	}
	
	/** 如：HouseholdRegistrationFormEntity */
	protected abstract String getDefinitionName();
	
	protected String getCatalog(){ return null; }
	
	protected abstract void initDefinition(TableDefinitionBuilder tdBuilder) throws Exception;
	
	@Override
	protected void onLoad(PanelEvent event) throws Exception {
		try{
			LogonUser user = event.getUser();
			AccountEntity entity = accountService.get(user.getId());
			PanelModel model = event.getModel();
			model.addObject("extstatus",entity.getExtStatus());
			TableDefinition tableDefinition = loadTableDefinition();
			model.addObject("displayableitems", tableDefinition.getDisplays());
			model.addObject("groupitems", tableDefinition.getGroups());
			
		}catch (Exception e) {
			e.printStackTrace();
		}
		event.setVmPath("search/standard-search");
	}

	/**
	 * 加载查询条件
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "!{key}/condition.json", method = GET)
	public Object conditionContent(){
		try{
			return loadTableDefinition().getQuerys(getUser());
		}catch (Exception e) {
			e.printStackTrace();
		}
		return Collections.emptyList();
	}

	/**
	 * 执行查询，并返回查询结果集给界面；
	 * 以json格式进行处理
	 * 
	 * 这里也可以改为vm的方式返回
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "!{key}/search.json", method = POST)
	public Object search(HttpServletRequest request){
		try{
			LogonUser user = getUser();
			AccountEntity entity = accountService.get(user.getId());
			SleepUtil.sleep(entity.getExtStatus(), 10000);
			SearchablePlatform searchablePlatform = tableDefinitionFactory.getSearchablePlatform();
			DefaultSearchableHttpRequest searchableConfig = new DefaultSearchableHttpRequest(getUser(), tableDefinition, request);
			
			searchableConfig.setTableObjectGenerator(createIdentifyTableGenerator());
			try(SearchableHandler searchableHandler = searchablePlatform.buildSearchableHandler(searchableConfig)){
			
				SearchableInputStream searchResultBuffer = searchableHandler.execute(searchableConfig);
				
				ObjectResultWriter objectResultWriter = new ObjectResultWriter(searchResultBuffer);
				objectResultWriter.flush();

				return objectResultWriter;
				
			}
//			return _doSearch(getUser(), request);
		}catch (Exception e) {
			e.printStackTrace();
			return JsonResult.error(e);
		}
	}
	
	@ResponseBody
	@RequestMapping(value = "!{key}/search.excel", method = POST)
	public void searchExcel(XSSFWorkbook workbook,HttpServletRequest request,HttpServletResponse response){
		try{
			SearchablePlatform searchablePlatform = tableDefinitionFactory.getSearchablePlatform();
			DefaultSearchableHttpRequest searchableConfig = new DefaultSearchableHttpRequest(getUser(), tableDefinition, request);
			
			searchableConfig.setTableObjectGenerator(createIdentifyTableGenerator());
			
			try(SearchableHandler searchableHandler = searchablePlatform.buildSearchableHandler(searchableConfig)){
			
				SearchableInputStream searchResultBuffer = searchableHandler.execute(searchableConfig);
				 SimpleDateFormat sd = new SimpleDateFormat("yyyyMMddHHmmss"); 
				 String name = sd.format(new Date());
				 String sheet=name;
				 XSSFSheet sheets = workbook.createSheet(sheet);
				ExcelResultWriter excelResultWriter = new ExcelResultWriter(searchResultBuffer,sheets);
				
				excelResultWriter.flush();
				
				String names = name + ".xlsx";
				response.setHeader("Content-disposition", "attachment;filename=" 
						+ new String(names.getBytes("gb2312"), "ISO8859-1"));
				 workbook.write(response.getOutputStream());
				
			}
//			return _doSearch(getUser(), request);
		}catch (Exception e) {
			e.printStackTrace();
			//return JsonResult.error(e);
		}
	}
	
	protected abstract IdentifyTableGenerator createIdentifyTableGenerator();

//	private SearchableResponse _doSearch(LogonUser user, HttpServletRequest request) throws Exception {
		
		/*
		 * 创建一个请求
		 * 创建处理器
		 */
//		HttpSearchableRequest searchableRequest = createSearchSearchRequest(user, searchContext, request);
//		SearchableHandler searchableHandler = searchablePlatform.buildSearchableHandler(searchableRequest);
//		
//		//searchRequest.init(searchContext, user, request);
//		
//		//return search(searchRequest, searchContext);
//		return null;
//	}

	@RequestMapping(value = "!{key}/search.html", method = POST)
	public String search(HttpServletRequest request, Model model){
		model.addAttribute("layout", "layout-empty.vm");
		try{
//			SearchableResponse sr = _doSearch(getUser(), request);
//			model.addAttribute("result", sr);
//			return "search/" + sr.path();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return "error";
	}

	protected SearchableHttpRequest createSearchSearchRequest(IOperator operator, 
			TableDefinition searchableContext,
			HttpServletRequest servletRequest) throws Exception{
		return new DefaultSearchableHttpRequest(operator, searchableContext, servletRequest);
	}
	
	//protected abstract SearchableHttpRequest createSearchSearchRequest(IOperator operator, TableDefinition searchableContext, HttpServletRequest servletRequest) throws Exception;
//	protected abstract SearchableResponse search(SearchableRequest request, SearchableContext context) throws Exception;
}
